#!/usr/bin/perl

#####################################################
# to look for sequence numbers within network frames
# will read from stdin
#####################################################

use strict;
use warnings;

if (@ARGV < 2) {
	print STDERR "Usage: $0 <tag_offset> <tag_length: [-]1..16> [<pcap text dump>]\n";
	print STDERR "negative length has something to do with endianness\n";
	exit 1;
}

my $offset = shift @ARGV;
my $length = shift @ARGV;
my $endian = 0; # big-endian by default

# UNDONE: add sanity check on offset
if ($length < 0) {
	$length = -$length;
	$endian = 1;
}

if ($length < 1) {
	$length = 1;
} elsif ($length > 16) {
	$length = 16;
}

my ($frame, $epoch, $tag);
my $stage = 0;

while (<>) {
# Frame NNN
#     Epoch Time: dddddddddd.ddddddddd seconds
# Data (xxx bytes)
# aaaa  hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh
	if ($stage == 0 && /^Frame (\d+):/) {
		$frame = $1;
		$epoch = -1;
		$tag = "";
		$stage++;
	} elsif ($stage == 1 && /^    Epoch Time: (\d+\.\d+)/) {
		$epoch = $1;
		$stage++;
	} elsif ($stage == 2 && /^Data \(\d+ bytes\)/) {
		$stage++;
	} elsif ($stage == 3 && /([0-9a-f]{4})  ([0-9a-f]{2}) ([0-9a-f]{2}) ([0-9a-f]{2}) ([0-9a-f]{2}) ([0-9a-f]{2}) ([0-9a-f]{2}) ([0-9a-f]{2}) ([0-9a-f]{2}) ([0-9a-f]{2}) ([0-9a-f]{2}) ([0-9a-f]{2}) ([0-9a-f]{2}) ([0-9a-f]{2}) ([0-9a-f]{2}) ([0-9a-f]{2}) ([0-9a-f]{2})/) {
		if ((hex($1) + 16) > $offset) {
			for (my $i = $offset - hex($1); $i < 16 && $i < $offset - hex($1) + $length; $i++) {
				if ($i >= 0) {
					my $add = substr $&, $-[2 + $i], ($+[2 + $i] - $-[2 + $i]);
					$tag = ($endian ? $add . $tag : $tag . $add);
				}
			}
		}
		if ((hex($1) + 16) >= $offset + $length) {
			print "$frame\t$epoch\t$tag\n";
			$stage = 0;
		}
	}
}
